#include <random>
#include <iostream>
#include "MainProcess.h"
#include "PopulationFactory.h"
#include "Utils/GlobalCppRandomEngine.h"
#include "Chromosome.h"

namespace GeneticAlgorithm {

    MainProcess::MainProcess() {
    }

    MainProcess::~MainProcess() {
        this->freeMemory();
    }

    void MainProcess::run(
        unsigned long numberOfChromosome,
        unsigned long lengthOfChromosome,
        long double min,
        long double max,
        unsigned long maxLoop,
        long double stopFitness,
        long double r
    ) {
        using namespace std;
        this->freeMemory(); // 防止重复调用run()没有释放上一次的内存
        this->numberOfChromosome = numberOfChromosome;
        this->lengthOfChromosome = lengthOfChromosome;
        this->min = min;
        this->max = max;
        this->r = r;
        this->init();
        this->maxFitness = this->population->getMaxFitnessChromosome()->getFitness();

        if (this->debug) {
            cout << "代数=0, 最大适应度=" << this->maxFitness << ", 个体信息=";
            this->population->getMaxFitnessChromosome()->dump();
        }

        while (this->loopNow < maxLoop && this->maxFitness < stopFitness) {
            this->population->nextGeneration(this->r);
            this->maxFitness = this->population->getMaxFitnessChromosome()->getFitness();
            this->loopNow++;
            if (this->debug) {
                cout << "代数=" << this->loopNow << ", 最大适应度=" << this->maxFitness << ", 个体信息=";
                this->population->getMaxFitnessChromosome()->dump();
            }
        }
        if (this->debug) {
            cout << "结束。" << endl;
        }
    }

    void MainProcess::runContinue(
        unsigned long maxLoop, // 这一次的最大迭代次数
        long double stopFitness, // 达到多大的适应度就立刻停止迭代
        long double r // 基因突变的概率
    ) {
        using namespace std;
        if (nullptr == this->population) {
            return;
        }
        this->r = r;
        unsigned long i = 0;
        this->maxFitness = this->population->getMaxFitnessChromosome()->getFitness();
        while (i < maxLoop && this->maxFitness < stopFitness) {
            this->population->nextGeneration(this->r);
            this->maxFitness = this->population->getMaxFitnessChromosome()->getFitness();
            this->loopNow++;
            if (this->debug) {
                cout << "代数=" << this->loopNow << ", 最大适应度=" << this->maxFitness << ", 个体信息=";
                this->population->getMaxFitnessChromosome()->dump();
            }
            i++;
        }
        if (this->debug) {
            cout << "结束。" << endl;
        }
    }

    void MainProcess::setDebug(bool enableDebug) {
        this->debug = enableDebug;
    }

    unsigned long MainProcess::getLoopNumber() {
        return this->loopNow;
    }

    long double MainProcess::getMaxFitness() {
        return this->maxFitness;
    }

    Chromosome* MainProcess::getMaxFitnessChromosome() {
        return this->population->getMaxFitnessChromosome();
    }

    void MainProcess::replaceChromosome(Chromosome* chromosome) {
        Chromosome* maxChromosome = this->population->getMaxFitnessChromosome();
        for (unsigned long offset = this->numberOfChromosome - 1; offset + 2 > 1; offset--) {
            if ((void*)this->population->getChromosome(offset) != (void*)maxChromosome) {
                this->population->replaceChromosome(offset, chromosome);
                return;
            }
        }
    }

    void MainProcess::init() {
        this->population = PopulationFactory().buildRandomPopulation(this->numberOfChromosome, this->lengthOfChromosome, this->min, this->max);
        this->loopNow = 0;
        this->maxFitness = 0.0;
    }

    void MainProcess::freeMemory() {
        if (nullptr != this->population) {
            delete this->population;
            this->population = nullptr;
        }
    }
}
